package com.chaos.gateway.config.interceptor;

import cn.hutool.core.util.ObjectUtil;
import com.chaos.framework.model.dto.result.Result;
import com.chaos.framework.model.exception.BusinessException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;


@Configuration
public class GlobalErrorWebExceptionHandler implements ErrorWebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        Map<String, String> result = new HashMap<>(6);
        String path = exchange.getRequest().getURI().getPath();
        ServerHttpResponse response = exchange.getResponse();
        if (response.isCommitted()) {
            return Mono.error(ex);
        }
        if (ex instanceof BusinessException) {
            Result exceptionResult = null;
            BusinessException businessException = (BusinessException) ex.getCause();
            if (ObjectUtil.isNotEmpty(businessException)) {
                exceptionResult = businessException.getResult();
            } else {
                exceptionResult = ((BusinessException) ex).getResult();
            }
            response.setStatusCode(HttpStatus.OK);
            Result finalExceptionResult = exceptionResult;
            return response.writeWith(Mono.fromSupplier(() -> {
                DataBufferFactory bufferFactory = response.bufferFactory();
                result.put("path", path);
                result.put("msg", finalExceptionResult.getMsg());
                result.put("code", String.valueOf(finalExceptionResult.getCode()));
                result.put("success", "false");
                ObjectMapper objectMapper = new ObjectMapper();
                try {
                    return bufferFactory.wrap(objectMapper.writeValueAsBytes(result));
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                    return null;
                }
            }));
        }
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        response.setStatusCode(HttpStatus.BAD_GATEWAY);

        ex.printStackTrace();

        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory bufferFactory = response.bufferFactory();
            result.put("path", path);
            result.put("msg", HttpStatus.BAD_GATEWAY.getReasonPhrase());
            result.put("code", String.valueOf(response.getStatusCode().value()));
            result.put("success", "false");
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                return bufferFactory.wrap(objectMapper.writeValueAsBytes(result));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return null;
            }
        }));
    }

}
